package com.zxf.appliction.dao;

import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONObject;

public interface IRedisDao {
	/**
	 * 切换到指定的数据库，数据库索引号 index 用数字值指定，以 0 作为起始索引值。 默认使用 0 号数据库。 <br>
	 * 根据源码注释发现,在cluster模式中,redis集群计划只使用 db0.
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param index
	 * @return
	 * @Version 1.0
	 */
	public boolean changeDB(int index);

	// -------------------------------------------List---------------------------------------------//
	/**
	 * 将一个或多个值 value 插入到列表 key 的 表头!<br>
	 * <br>
	 * 表头!表头!!!!!.<br>
	 * <br>
	 * 如果有多个 value 值，那么各个 value 值按从左到右的顺序依次插入到表头：<br>
	 * 比如说，对空列表 mylist 执行命令 LPUSH mylist a b c ，列表的值将是 c b a ，<br>
	 * 这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。
	 * 
	 * 如果 key 不存在，一个空列表会被创建并执行 LPUSH 操作。
	 * 
	 * 当 key 存在但不是列表类型时，打印日志,并返回false;
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param values
	 * @return
	 * @Version 1.0
	 */
	public boolean LPush(String key, String... values);

	/**
	 * 将一个或多个值 value 插入到列表 key 的 表尾!<br>
	 * <br>
	 * 表尾!表尾!!尾!!!.<br>
	 * <br>
	 * 如果有多个 value 值，那么各个 value 值按从左到右的顺序依次插入到表尾：
	 * 
	 * 比如对一个空列表 mylist 执行 RPUSH mylist a b c ，得出的结果列表为 a b c ，
	 * 
	 * 等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。
	 * 
	 * 如果 key 不存在，一个空列表会被创建并执行 LPUSH 操作。
	 * 
	 * 当 key 存在但不是列表类型时，打印日志,并返回false;
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param values
	 * @return
	 * @Version 1.0
	 */
	public boolean RPush(String key, String... values);

	/**
	 * 将值 value 插入到列表 key 当中，位于值 pivot 之前
	 * 
	 * 当 pivot 不存在于列表 key 时，不执行任何操作。
	 * 
	 * 当 key 不存在时， key 被视为空列表，不执行任何操作。
	 * 
	 * 如果 key 不是列表类型，打印一个异常,并返回false;
	 * 
	 * 
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param pivot
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public boolean LInsertBefore(String key, String pivot, String value);

	/**
	 * 将值 value 插入到列表 key 当中，位于值 pivot 之后
	 * 
	 * 当 pivot 不存在于列表 key 时，不执行任何操作。
	 * 
	 * 当 key 不存在时， key 被视为空列表，不执行任何操作。
	 * 
	 * 如果 key 不是列表类型，打印一个异常,并返回false;
	 * 
	 * 
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param pivot
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public boolean LInsertAfter(String key, String pivot, String value);

	/**
	 * 返回列表 key 中，下标为 index 的元素。
	 * 
	 * 下标(index)参数 start 和 stop 都以 0 为底，也就是说，以 0 表示列表的第一个元素，以 1 表示列表的第二个元素，以此类推。
	 * 
	 * 你也可以使用负数下标，以 -1 表示列表的最后一个元素， -2 表示列表的倒数第二个元素，以此类推。
	 * 
	 * 如果 key 不是列表类型，打印异常信息并返回null;
	 * 
	 * 如果 index 参数的值不在列表的区间范围内(out of range)，返回 null
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param index
	 * @return
	 * @Version 1.0
	 */
	public String LIndex(String key, Integer index);

	/**
	 * 返回列表 key 的长度。
	 * 
	 * 如果 key 不存在，则 key 被解释为一个空列表，返回 0 .
	 * 
	 * 如果 key 不是列表类型，输入错误信息,返回-1
	 * 
	 * 其他异常,返回-1
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @return
	 * @Version 1.0
	 */
	public Long LLength(String key);

	/**
	 * 移除并返回列表 key 的头元素。
	 * 
	 * 当 key 不存在时，返回 null 。
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @return
	 * @Version 1.0
	 */
	public String LPop(String key);

	/**
	 * 返回列表 key 中指定区间内的元素，区间以偏移量 start 和 stop 指定。<br>
	 * 
	 * 下标(index)参数 start 和 stop 都以 0 为底，也就是说，<br>
	 * 
	 * list 的第一个元素的 index 为 0 .
	 * 
	 * 注意LRANGE命令和编程语言区间函数的区别, 假如你有一个包含一百个元素的列表，<br>
	 * 
	 * 对该列表执行 LRANGE list 0 10 ，结果是一个包含11个元素的列表，<br>
	 * 
	 * 这表明 stop 下标也在 LRANGE 命令的取值范围之内(闭区间) .<br>
	 * 
	 * 超出范围的下标 超出范围的下标值不会引起错误。<br>
	 * 
	 * 如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大，那么 LRANGE 返回一个空列表。<br>
	 * 
	 * 如果 stop 下标比 end 下标还要大，Redis将 stop 的值设置为 end 。<br>
	 * 
	 * 
	 * 如果 Key 不是 一个list或其他异常,则返回null;
	 * 
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param start
	 *            起始位置
	 * @param end
	 *            结束位置
	 * @return
	 * @Version 1.0
	 */
	public List<String> LRange(String key, Long start, Long end);

	/**
	 * 根据参数 count 的值，移除列表中与参数 value 相等的元素。返回被移除元素的数量.<br>
	 * 
	 * 因为不存在的 key 被视作空表(empty list)，所以当 key 不存在时， 总是返回 0 。<br>
	 * 
	 * 当 key 不是一个list类型或其他异常,返回-1<br>
	 * 
	 * <h3>count 的值可以是以下几种：</h3>
	 * <ul>
	 * <li>count > 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count 。</li>
	 * 
	 * <li>count < 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值。</li>
	 * 
	 * <li>count = 0 : 移除表中所有与 value 相等的值。</li>
	 * </ul>
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param count
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public Long LRemove(String key, Integer count, String value);

	/**
	 * 将列表 key 下标为 index 的元素的值设置为 value 。
	 * 
	 * 当 index 参数超出范围，或对一个空列表( key 不存在)进行 LSET 时，返回false
	 * 
	 * 当 key 不是一个list时,返回false;
	 * 
	 * @Created by zyj on 2016年12月19日
	 * @param key
	 * @param index
	 * @param value
	 * @return
	 * @Version 1.0
	 */
	public boolean LSet(String key, Long index, String value);

	// ---------------------------------------------------Set-----------------------------------------------------//
	/**
	 * 判断 member 元素是否集合 key 的成员。<br>
	 * 如果 member 元素不是集合的成员，或 key 不存在，返回 false;<br>
	 * 如果key类型错误,打印错误日志,并返回false;
	 * 
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 * @param member
	 * @return
	 * @Version 1.0
	 */
	public boolean Sismember(String key, String member);

	/**
	 * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。<br>
	 * 当 key 不是集合类型，打印错误日志,并返回false
	 * 
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 *            setKey
	 * @param smembers
	 *            元素
	 * @return
	 * @Version 1.0
	 */
	public boolean SRemove(String key, String... members);

	/**
	 * 获取set集合<br>
	 * 返回集合 key 中的所有成员。<br>
	 * 不存在的 key 被视为空集合。<br>
	 * Key不是一个set类型时,返回null;<br>
	 * 其他错误返回null;
	 * 
	 * @param key
	 * @return
	 */
	public Set<String> SMembers(String key);

	/**
	 * 设置set集合<br>
	 * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略。<br>
	 * 假如 key 不存在，则创建一个只包含 member 元素作成员的集合。<br>
	 * 当 key 不是集合类型时，打印错误,并返回false;
	 * 
	 * @param key
	 * @param members
	 *            元素数组
	 * @param ttlSeconds
	 *            生存时间,设置为null或为-1时表示不设置
	 * @return
	 */
	public boolean SAdd(String key, Integer ttlSeconds, String... members);

	// ------------------------------------------Hash-------------------------------------------//

	/**
	 * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略。<br>
	 * 如果key的类型不是hash,则打印日志,返回false;
	 * 
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 * @param fields
	 * @return
	 * @Version 1.0
	 */
	public boolean HDel(String key, String... fields);

	/**
	 * 获取HashMap<br>
	 * 类型不是hash时打印错误信息,返回null<br>
	 * key不存在返回 {}
	 * 
	 * 
	 * @param key
	 * @return
	 */
	public Map HGetAll(String key);

	/**
	 * 读取HashMap中的一个字段<br>
	 * key必须为Hash类型,否则打印异常返回null<br>
	 * 读取异常时,返回null
	 * 
	 * @param key
	 * @param fieldName
	 * @return
	 */
	public String HMGetSingleField(String key, String fieldName);

	/**
	 * 获取hashmap中的多个字段的值,返回json对象. 异常返回null<br>
	 * 如果key不存在返回空的json对象<br>
	 * 若hash中不存在给出的 fieldName ,则在返回的json对象中不包含该key <br>
	 * e.g. fieldNames = ["f1","f2","f4"]; 其中f4不存在,结果 = {"f1":"v1","f2":"v2"}
	 * 
	 * @param key
	 * @param fieldNames
	 * @return
	 */
	public JSONObject HMGetMultValue(String key, String... fieldNames) throws ArrayIndexOutOfBoundsException;

	/**
	 * 设置map的多个字段<br>
	 * 
	 * 
	 * @param key
	 * @param ttlSeconds
	 *            生存时间
	 * @param fieldAndValue
	 *            数组形式 两个为一对, e.g. ['field1','value1','field2','value2'.....]
	 * @return
	 */
	public boolean HMSetMultField(String key, Integer ttlSeconds, String... fieldAndValue);

	/**
	 * 将哈希表 key 中的域 field 的值设为 value 。 <br>
	 * 如果 key 不存在，一个新的哈希表被创建并进行 HSET 操作。<br>
	 * 如果域field 已经存在于哈希表中，旧值将被覆盖.<br>
	 * 当Key的类型不是一个Hash时,将输出错误日志,并返回false
	 * 
	 * @param key
	 *            hash的Key值
	 * @param fieldName
	 *            域的名字
	 * @param fieldValue
	 *            域的值
	 * @return
	 */
	public boolean HMSetSingleField(String key, String fieldName, String fieldValue);

	/**
	 * 设置HashMap,设置控制将打印异常信息,并返回false,
	 * 
	 * 如果hash中已经包含了给出的值,那么新的值将覆盖他.
	 * 
	 * @param key
	 * @param value
	 *            不可以为null或者为空
	 * @param ttlSeconds
	 *            过期时间 给出null或者 -1 表示不过期
	 * @return
	 */
	public boolean HMSet(String key, Map value, Integer ttlSeconds);

	/**
	 * 判断Hash类型key中是否含有@fieldName字段<br>
	 * 
	 * 
	 * @param key
	 *            类型必须为Hash,否则抛出异常
	 * @param fieldName
	 * @return
	 * @throws IllegalArgumentException
	 */
	public boolean HashExists(String key, String fieldName) throws IllegalArgumentException;

	// -----------------------------------------String------------------------------------------//
	/**
	 * 仅用于获取redis中String类型数据,redis中key不存在时返回null,<br>
	 * 当key的value值类型不为String时返回空,并在日志中打印错误信息
	 * 
	 * @param key
	 * @return 返回一个指定key的value值,当value不为String类型时打印异常信息并返回null,当key不存在时返回null
	 */
	public String getString(String key);

	/**
	 * 设置String类型值,value的长度不能超过 1073741824 字节(1GB).
	 * 
	 * @param key
	 * @param value
	 * @param ttlSeconds
	 *            设置过期时间,设置为null或-1表示不设置
	 * @return
	 */
	public boolean setString(String key, String value, Integer ttlSeconds);

	// -----------------------------------Key------------------------------- //

	/**
	 * 删除给定的一个或多个 key 。<br>
	 * 不存在的 key 会被忽略。<br>
	 * 异常时返回false;
	 * 
	 * 最好不要多个一起删除,除非你确定他们在同一个slots内,否则将抛出异常.
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param keys
	 * @return
	 * @Version 1.0
	 */
	public boolean Del(String... keys);

	/**
	 * 获取Key的类型 , 异常返回空
	 * 
	 * @Created by zyj on 2016年12月5日
	 * @param key
	 * @return
	 * @Version 1.0
	 */
	public String getType(String key);

	/**
	 * 判断Key是否存在
	 * 
	 * 错误时打印异常日志,返回false
	 * 
	 * @param key
	 * @return
	 */
	public boolean isExists(String key);

	/**
	 * 设置key生存时间,单位秒
	 * 
	 * 发生异常打印异常信息,返回false;
	 * 
	 * @param key
	 * @param seconds
	 * @return
	 */
	public boolean Expire(String key, Integer seconds);

	/**
	 * 设置key永不过期
	 * 
	 * 发生异常打印异常日志,返回false;
	 * 
	 * @param key
	 * @return
	 */
	public boolean Persist(String key);

}
